package cc.rengu.igas.share.core.service.trans;

import cc.rengu.igas.share.common.enums.RespCodeEnum;
import cc.rengu.igas.share.core.model.BankCodeInfo;
import cc.rengu.igas.share.core.model.UpacTokenPayInfo;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.BompService;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.BompServiceImpl;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.igas.share.core.service.base.NoticeService;
import cc.rengu.igas.share.facade.request.UpacSignResultNoticeRequest;
import cc.rengu.igas.share.facade.response.UpacSignResultNoticeResponse;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.SignAcctInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.SignAcctInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.BinInfo;
import cc.rengu.oltp.service.common.entity.SignAcctInfo;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.BinInfoService;
import cc.rengu.oltp.service.realize.impl.BinInfoServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;

/**
 * 银联全渠道支付开通通知服务
 * Created by 王成 on 2018/6/3.
 */
public class UpacSignResultNoticeService extends NoticeService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        UpacSignResultNoticeRequest upacSignResultNoticeRequest = new UpacSignResultNoticeRequest();
        ConvertUtil.convertOutput(upacSignResultNoticeRequest);
        return upacSignResultNoticeRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        UpacSignResultNoticeRequest upacSignResultNoticeRequest = (UpacSignResultNoticeRequest) request;
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        if ("00".equals(upacSignResultNoticeRequest.getRespCode())) {
            rglog.info("原签约交易全渠道应答成功，更新原签约交易信息");
            String instId = upacSignResultNoticeRequest.getHeader().getInstId();
            String acqReserved = upacSignResultNoticeRequest.getAcqReserved();
            byte[] bytes = Base64.decodeBase64(acqReserved);
            JSONObject acqReservedJson = JSONObject.parseObject(new String(bytes), JSONObject.class);
            rglog.debug("无跳转保留域中的数据:<{}>", acqReservedJson);
            String orderId = acqReservedJson.getString("signOrderId");
            String signTransType = acqReservedJson.getString("transType");
            boolean isCreditFlag = Boolean.getBoolean(acqReservedJson.getString("isCreditGrant"));

            //查找原签约申请信息
            SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
            SignAcctInfo signAcctInfo = signAcctInfoMapper.selectSignAcctInfoBySignSeqNum(instId, orderId);
            if (null == signAcctInfo) {
                rglog.info("原全渠道签约申请交易不存在");
                throw new BizException(RespCodeEnum.SIGN_INFO_NOT_EXIST.getRespCode(), RespCodeEnum.SIGN_INFO_NOT_EXIST.getRespDesc());
            }

            //获取卡BIN
            BinInfoService binInfoService = new BinInfoServiceImpl();
            BinInfo cardBinInfo = binInfoService.getCardBinInfo(signAcctInfo.getSignAcctNo());
            if (null == cardBinInfo) {
                rglog.info("该卡bin信息不存在，cardNo:<{}>", signAcctInfo.getSignAcctNo());
                throw new BizException(RespCodeEnum.ORDER_NOT_EXIST.getRespCode(), RespCodeEnum.ORDER_NOT_EXIST.getRespDesc());
            }

            //查询银联联行号信息
            BompService bompService = new BompServiceImpl();
            BankCodeInfo bankCodeInfo = bompService.getBankCodeInfoByCupsInstId(cardBinInfo.getIssuerCode(), cardBinInfo.getCardSign());
            if (null == bankCodeInfo) {
                rglog.error("根据银行机构号获取联行行号失败,cupsInstId:<{}>,cardSign:<{}>", instId, cardBinInfo.getCardSign());
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }

            //获取通道签约相关信息
            JSONObject customerInfo = JSON.parseObject(upacSignResultNoticeRequest.getAcqReserved());
            rglog.info("customerInfo=[{}]", customerInfo);

            //获取通道签约标记相关信息
            UpacTokenPayInfo tokenPayInfo = new UpacTokenPayInfo();
            if (upacSignResultNoticeRequest.getTokenPayData() != null) {
                tokenPayInfo = (UpacTokenPayInfo) convertKvStr2Bean(upacSignResultNoticeRequest.getTokenPayData(), UpacTokenPayInfo.class);
                rglog.debug("tokenPayInfo=[{}]", upacSignResultNoticeRequest.getTokenPayData());
            }

            //获取签约用户信息
            UserService userService = new UserServiceImpl();
            UserInfo userInfo = userService.getUserInfoByUserId(instId, signAcctInfo.getUserId());
            if (null == userInfo) {
                rglog.error("签约用户信息不存在!", signAcctInfo.getUserId());
                throw new BizException(RespCodeEnum.USER_INFO_NOT_EXIST.getRespCode(), RespCodeEnum.USER_INFO_NOT_EXIST.getRespDesc());
            }

            //判断是否为重新签约
            String userId = signAcctInfo.getUserId();
            if (!StringUtil.isEmptyOrNull(signTransType) && "1".equals(signTransType)) {
                rglog.info("银联全渠道重新签约，需要注销原用户及签约信息!");
                userInfo.setUserStatus("01");
                boolean updateFlag = userService.updateUserInfo(userInfo);
                if (!updateFlag) {
                    rglog.error("重新签约更新原用户标识<{}>的用户信息为注销失败!", userInfo.getUserId());
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }
                //重新生成用户ID
                if (!isCreditFlag && !"00".equals(signAcctInfo.getSignType())) {
                    rglog.debug("当前商户为非授信商户:<{}>且签约等级不是行级:<{}>，注销之前的用户信息，生成新的用户，oldUserId:<{}>",
                            isCreditFlag, signAcctInfo.getSignType(), userInfo.getUserId());
                    userId = instId + DateUtil.getCurrentDate() + sysSeqNum.substring(sysSeqNum.length() - 8);
                    rglog.debug("非授信商户重新生成userId:<{}>");
                } else {
                    userId = instId + DateUtil.getCurrentDate() + sysSeqNum.substring(sysSeqNum.length() - 8);
                }
                signAcctInfo.setUserId(userId);
                signAcctInfo.setSignStatus(AppParamConstant.NO);
                int iReturnCode = signAcctInfoMapper.updateSignAcctInfoByPrimaryKey(signAcctInfo);
                if (0 != iReturnCode) {
                    rglog.error("重新签约更新原签约状态为解约失败,signToken:<{}>", signAcctInfo.getSignToken());
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }
            }

            //更新签约数据
            signAcctInfo.setSignToken(bankCodeInfo.getBankBranchCode() + "|" + tokenPayInfo.getToken());
            signAcctInfo.setSignBankNo(bankCodeInfo.getBankBranchCode());
            signAcctInfo.setSignBankName(bankCodeInfo.getBankBranchName());
            signAcctInfo.setReserveMobileNo(customerInfo.getString("phoneNo"));
            signAcctInfo.setSignExpiryDate(tokenPayInfo.getTokenEnd().substring(0, 8));
            if ("1".equals(upacSignResultNoticeRequest.getActivateStatus())) {
                signAcctInfo.setSignStatus(AppParamConstant.YES);
            } else {
                signAcctInfo.setSignStatus(AppParamConstant.NO);
            }
            int iReturnCode = signAcctInfoMapper.updateSignAcctInfoBySignAcctNo(signAcctInfo);
            if (0 != iReturnCode) {
                rglog.error("更新签约信息表失败,signAcctInfo:<{}>", JSONObject.toJSONString(signAcctInfo));
            } else {
                rglog.debug("更新签约信息表成功,signAcctInfo:<{}>", JSONObject.toJSONString(signAcctInfo));
            }

            //登记或者更新用户信息
            if (!StringUtil.isEmptyOrNull(signTransType) && "1".equals(signTransType)) {
                UserInfo newUserInfo = new UserInfo();
                BeanUtil.beanCopy(userInfo, newUserInfo);
                String passwordSalt = instId + DateUtil.getCurrentDate() + sysSeqNum.substring(sysSeqNum.length() - 8);
                newUserInfo.setUserId(userId);
                newUserInfo.setTransPasswordSalt(passwordSalt);
                newUserInfo.setTransPasswordErrorTimes(0);
                newUserInfo.setTransPassword("");
                newUserInfo.setUserStatus("00");
                boolean updateFlag = userService.updateUserInfo(newUserInfo);
                if (!updateFlag) {
                    rglog.warn("登记用户信息表失败,userInfo:<{}>", JSONObject.toJSONString(newUserInfo));
                    throw new BizException(RespCodeEnum.USER_INFO_INSERT_ERROR.getRespCode(), RespCodeEnum.USER_INFO_INSERT_ERROR.getRespDesc());
                }
            } else if (StringUtil.isEmptyOrNull(userInfo.getMobileNo())) {
                /* 若用户首次签约他行卡，收银台用户表更新用户签约账号的银行预留手机号 */
                userInfo.setMobileNo(signAcctInfo.getReserveMobileNo());
                boolean updateFlag = userService.updateUserInfo(userInfo);
                if (!updateFlag) {
                    rglog.warn("更新用户信息表失败,userInfo:<{}>", JSONObject.toJSONString(userInfo));
                }
            }
        }
        BizResponse response = new BizResponse<>();
        UpacSignResultNoticeResponse upacSignResultNoticeResponse = new UpacSignResultNoticeResponse();
        ConvertUtil.convertOutput(upacSignResultNoticeResponse);
        response.setResult(upacSignResultNoticeResponse);
        response.setRspSysId(AppParamConstant.IGAS);
        response.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        response.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return response;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        UpacSignResultNoticeResponse upacSignResultNoticeResponse = (UpacSignResultNoticeResponse) bizResponse.getResult();
        ConvertUtil.convertInput(upacSignResultNoticeResponse);
    }
}
